home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 6984 / 6984.xpi / chrome / lazarus.jar / content / xul-tree.js < prev   
Text File  |  2009-11-24  |  9KB  |  285 lines

  1.  
  2. this.Tree = this.Tree || {};
  3.  
  4. /**
  5. * make a tree sortable
  6. */
  7. Tree.Sorter = function(tree){
  8.  
  9.     //event handlers change the "this" object
  10.     var _this = this;
  11.     
  12.     //keep a reference to the tree
  13.     _this.tree = tree;
  14.     
  15.     //the original (full) set of data for the tree
  16.     _this.tree.origData = _this.tree.origData || null;
  17.     
  18.     //the current dataset
  19.     _this.tree.data = _this.tree.data || null;
  20.     
  21.     
  22.     /**
  23.     * prepares a value for the compare function
  24.     */
  25.     _this.prepareForSort = function(val){
  26.         if (val === null){return ""}
  27.         switch (typeof val){
  28.             case "string":
  29.                 val = val.toLowerCase();
  30.                 break;
  31.                 
  32.             case "number":
  33.             default:
  34.                 //do nothing
  35.         }
  36.         return val;
  37.     }
  38.     
  39.     /**
  40.     * sorts the data by the given column
  41.     */
  42.     _this.sortData = function(columnId, desc){
  43.     
  44.         //build a sorting function for this column
  45.         //TODO: expens sorting function to handle different datatypes (numbers/strings/dates) 
  46.         var sortFn = function(a, b){
  47.             var aa = _this.prepareForSort(a[columnId]);
  48.             var bb = _this.prepareForSort(b[columnId]);
  49.             
  50.             if (aa < bb){
  51.                 return -1;
  52.             }
  53.             else if (aa > bb){
  54.                 return 1;
  55.             }
  56.             else {
  57.                 return 0;
  58.             }  
  59.         }
  60.         
  61.         //and sort the current dataset using this function
  62.         _this.tree.data.sort(sortFn);
  63.         if (desc){
  64.             _this.tree.data.reverse();
  65.         }
  66.         
  67.         //and set view
  68.         _this.tree.refresh(); 
  69.     }
  70.     
  71.     
  72.     /**
  73.     * 
  74.     */
  75.     _this.onColumnClick = function(evt){
  76.         //make sure this is a treecol and not an element within the column
  77.         var ele = evt.target;
  78.         while(ele && ele.nodeName != "treecol"){
  79.             ele = ele.parentNode;
  80.             if (!ele){
  81.                 throw Error("Tree.Sorter: Unable to find column clicked");
  82.             }
  83.         }
  84.         
  85.         //check by putting extra element within the 
  86.         _this.sortByColumn(ele);
  87.     }
  88.     
  89.     /**
  90.     * 
  91.     */
  92.     _this.sortByColumn = function(sortColumn, dir){
  93.        
  94.         //only sort columns with a sort id attribute
  95.         var id = sortColumn.getAttribute("id");
  96.         
  97.         if (id && sortColumn.getAttribute("sortable") !== "false"){
  98.             dir = dir || ((sortColumn.getAttribute("sortDirection") == "descending") ? "ascending" : "descending");
  99.             //set the sort direction on the various columns
  100.             //setting these will make the sort option persist
  101.             _this.tree.setAttribute("sortDirection", dir);
  102.             _this.tree.setAttribute("sortId", id);
  103.             
  104.             //and update the sort direction
  105.             for (var i=0; i<_this.treeColumns.length; i++){
  106.                 _this.treeColumns[i].setAttribute("sortDirection", (_this.treeColumns[i] == sortColumn) ? dir : "");
  107.             }
  108.             _this.sortData(id, dir == "descending");
  109.             return true;
  110.         }
  111.         else {
  112.             return false;
  113.         }
  114.     }
  115.     
  116.     
  117.     /**
  118.     * attach event handlers to the tree
  119.     */
  120.     _this.initTree = function(){
  121.         _this.treeColumns = _this.tree.getElementsByTagName("treecol");
  122.         
  123.         for (var i=0; i<_this.treeColumns.length; i++){
  124.             _this.treeColumns[i].addEventListener("click", _this.onColumnClick, false);
  125.         }
  126.         
  127.         var filterBoxId = _this.tree.getAttribute("filterbox");
  128.         if (filterBoxId){
  129.             _this.filterBox = document.getElementById(filterBoxId);
  130.             if (_this.filterBox){
  131.                 _this.filterBox.addEventListener("keyup", _this.onFilterChange, false);
  132.             }
  133.             else {
  134.                 throw Error("Tree.Sorter: Unable to find filterbox ["+ filterBoxId +"]");
  135.             }
  136.         }
  137.     }
  138.     
  139.     /**
  140.     * sets the initial dataset
  141.     */
  142.     _this.tree.initData = function(data){
  143.         //save a copy of the original dataset
  144.         _this.tree.origData = data;
  145.         _this.tree.data = data;
  146.         
  147.         //sort the data by the saved sort column
  148.         var initSortColumn = document.getElementById(_this.tree.getAttribute("sortId"));
  149.         
  150.         if (initSortColumn && _this.sortByColumn(initSortColumn, _this.tree.getAttribute("sortDirection"))){
  151.             //all good data filled in
  152.         }
  153.         else {
  154.             //need to fill in the data
  155.             _this.tree.refresh();
  156.         }
  157.     }
  158.     
  159.     /**
  160.     * 
  161.     */
  162.     _this.getFilteredData = function(){
  163.     
  164.         var filter = (_this.filterBox && _this.filterBox.value) ? Tree.trim(_this.filterBox.value) : '';
  165.         
  166.         if (filter){
  167.             filter = _this.prepareForSort(filter);
  168.             var filtered = [];
  169.             for (var i=0; i<_this.tree.origData.length; i++){
  170.                 var include = false;
  171.                 for(var id in _this.tree.origData[i]){
  172.                     if (_this.prepareForSort(_this.tree.origData[i][id]).toString().indexOf(filter) > -1){
  173.                         include = true;
  174.                         break;
  175.                     }
  176.                 }
  177.                 if (include){
  178.                     filtered.push(_this.tree.origData[i]);
  179.                 }
  180.             }
  181.             return filtered;
  182.         }
  183.         else {
  184.             return _this.tree.origData;
  185.         }
  186.     }
  187.     
  188.     _this.onFilterChange = function(){
  189.     
  190.         if (_this.timerRunFilter){
  191.             clearTimeout(_this.timerRunFilter);
  192.         }
  193.         _this.timerRunFilter = setTimeout(_this.tree.filterData, 200);
  194.     }
  195.     
  196.     /**
  197.     * filter the data
  198.     */
  199.     _this.tree.filterData = function(){
  200.         _this.tree.data = _this.getFilteredData();
  201.         _this.tree.refresh();    
  202.     }
  203.     
  204.     /**
  205.     * updates the current view
  206.     */
  207.     _this.tree.refresh = function(fullRefresh){
  208.     
  209.         var data = _this.tree.data;
  210.         
  211.         //keep the tree looking at the same row (if possible)
  212.         var topRow = _this.tree.treeBoxObject.getFirstVisibleRow();
  213.         _this.tree.view = new _this.tree.nsITreeView(data);
  214.         _this.tree.data = data;
  215.         if (topRow){
  216.             _this.tree.treeBoxObject.scrollToRow(topRow);
  217.         }
  218.     }
  219.     
  220.     /**
  221.     * a simplistic nsITreeView for sorting by data value.
  222.     * This function should be overwritten if the tree needs a more complex view.
  223.     * If an nsITreeView is already attached then we will use that instead.
  224.     */
  225.     _this.tree.nsITreeView = _this.tree.nsITreeView || function(data){
  226.         this.rowCount = data.length;
  227.         this.getCellText = function(row, col){
  228.             return data[row][col.id];
  229.         };
  230.         this.getCellValue = function(row, col){
  231.             return data[row][col.id];
  232.         };
  233.         this.setTree = function(treebox){
  234.             this.treebox = treebox;
  235.         };
  236.         this.isEditable = function(row, col){
  237.             return col.editable;
  238.         };
  239.         this.getImageSrc = function(row, col){}
  240.         this.isContainer = function(row){return false;};
  241.         this.isSeparator = function(row){return false;};
  242.         this.isSelectable = function(){};
  243.         this.isSorted = function(){return false;};
  244.         this.getLevel = function(row){return 0;};
  245.         this.getImageSrc = function(row, col){return null;};
  246.         this.getRowProperties = function(row, props){};
  247.         this.getCellProperties = function(row, col, props){};
  248.         this.getColumnProperties = function(colid, col, props){};
  249.         this.cycleHeader = function(col, elem){};
  250.     }
  251.     
  252.     _this.initTree();
  253. }
  254.  
  255. /**
  256. * trim whitespace from beginning and end of a string
  257. */
  258. Tree.trim = function(str){
  259.     return str.replace(/^\s+/, '').replace(/\s+$/, '');
  260. }
  261.  
  262. /**
  263. * finds all tree elements with class of "sortable" and converts 
  264. * them into sortable trees
  265. */
  266. Tree.Sorter.initDoc = function(){
  267.     var trees = document.getElementsByTagName("tree");
  268.     for (var i=0; i<trees.length; i++){
  269.         if (Tree.hasClass(trees[i], "sortable")){
  270.             new Tree.Sorter(trees[i]);
  271.         }
  272.     }
  273. }
  274.  
  275.  
  276. /* == helper functions == */
  277.  
  278. /**
  279. * return TRUE if element has this class 
  280. */
  281. Tree.hasClass = function(ele, needle){
  282.     var eleClass = " "+ ele.getAttribute("class").toLowerCase().replace(/\s+/g, " ") +" ";
  283.     return (eleClass.indexOf(" "+ needle.toLowerCase() +" ") > -1);
  284. }
  285.